package spark.math;

public class Vector4 {
	public float x;
	public float y;
	public float z;
	public float w;

	public Vector4() {
		this(0, 0, 0, 0);
	}

	public Vector4(float x, float y, float z, float w) {
		this.x = x;
		this.y = y;
		this.z = z;
		this.w = w;
	}

	public Vector4(final Vector4 source) {
		this.x = source.x;
		this.y = source.y;
		this.z = source.z;
		this.w = source.w;
	}

	public static Vector4 normalize(final Vector4 aVector) {
		Vector4 normalizedVector = new Vector4(aVector);
		normalizedVector.normalize();
		return normalizedVector;
	}

	public void normalize() {
		float length = this.length();

		if(length > 0) {
			x /= length;
			y /= length;
			z /= length;
			w /= length;
		}
	}

	public static float length(final Vector4 aVector) {
		return (float) Math.sqrt(
				aVector.x * aVector.x +
				aVector.y * aVector.y +
				aVector.z * aVector.z +
				aVector.w * aVector.w);
	}

	public float length() {
		return length(this);
	}

	public static Vector4 transform(final Vector4 aSource, final Matrix aSourceMatrix) {
		Vector4 newVector = new Vector4(aSource);
		newVector.transform(aSourceMatrix);
		return newVector;
	}

	public void transform(final Matrix aSourceMatrix) {
		Matrix tempMatrix = new Matrix(aSourceMatrix);

		float newX = tempMatrix.getMatrix()[Matrix._11] * x + tempMatrix.getMatrix()[Matrix._21] * y + tempMatrix.getMatrix()[Matrix._31] * z + tempMatrix.getMatrix()[Matrix._41] * w;
		float newY = tempMatrix.getMatrix()[Matrix._12] * x + tempMatrix.getMatrix()[Matrix._22] * y + tempMatrix.getMatrix()[Matrix._32] * z + tempMatrix.getMatrix()[Matrix._42] * w;
		float newZ = tempMatrix.getMatrix()[Matrix._13] * x + tempMatrix.getMatrix()[Matrix._23] * y + tempMatrix.getMatrix()[Matrix._33] * z + tempMatrix.getMatrix()[Matrix._43] * w;
		float newW = tempMatrix.getMatrix()[Matrix._14] * x + tempMatrix.getMatrix()[Matrix._24] * y + tempMatrix.getMatrix()[Matrix._34] * z + tempMatrix.getMatrix()[Matrix._44] * w;

		x = newX;
		y = newY;
		z = newZ;
		w = newW;
	}

	public static Vector4 add(final Vector4 left, final Vector4 right) {
		return new Vector4(left.x + right.x, left.y + right.y, left.z + right.z, left.w + right.w);
	}

	public void add(final Vector4 vector) {
		this.x += vector.x;
		this.y += vector.y;
		this.z += vector.z;
		this.w += vector.w;
	}

	public static Vector4 substract(final Vector4 left, final Vector4 right) {
		return new Vector4(left.x - right.x, left.y - right.y, left.z - right.z, left.w - right.w);
	}

	public void substract(final Vector4 vector) {
		this.x -= vector.x;
		this.y -= vector.y;
		this.z -= vector.z;
		this.w -= vector.w;
	}

	public static Vector4 multiply(final Vector4 vector, final float scalar) {
		return new Vector4(vector.x * scalar, vector.y * scalar, vector.z * scalar, vector.w * scalar);
	}

	public void multiply(final float scalar) {
		this.x *= scalar;
		this.y *= scalar;
		this.z *= scalar;
		this.w *= scalar;
	}

	public static Vector4 divide(final Vector4 vector, final float scalar) {
		return new Vector4(vector.x / scalar, vector.y / scalar, vector.z / scalar, vector.w / scalar);
	}

	public void divide(final float scalar) {
		this.x /= scalar;
		this.y /= scalar;
		this.z /= scalar;
		this.w /= scalar;
	}
}
